/**
  ******************************************************************************
  * @file    FreeRTOS_CLI_Task.c
  * @author  Iron
  * @date 	 2018-07-09
  * @version v1.0
  * @brief   FreeRTOS CLI Task c file
  */

/** @addtogroup GROUP_TASK
  * @{
  */

/* includes ------------------------------------------------------------------*/
#include <string.h>
#include "tasks_common.h"
#include "FREERTOS_CLI.h"
#include "bsp.h"

#ifdef BSP_CLI_ENABLE
// DEBUG
#include "debug_log.h"
#define LOG_LOCAL_LEVEL DBG_LOG_DEBUG
DBG_LOG_TAG("CLI");

/* private typedef -----------------------------------------------------------*/
/* private macro -------------------------------------------------------------*/
#define cli_puts(s)		bsp_puts(s)
#define cli_getc(s)		bsp_getc()
#define cli_putc(c)		bsp_putc(c)

#define WELLCOM_MESSAGE "\r\nFreeRTOS command shell.\r\nType \"help\" to view a list of registered commands.\r\n\r\n>"
#define CMD_TAG		"\r\n>"
#define NEW_LINE 	"\r\n"

/* DEL acts as a backspace. */
#define cmdASCII_DEL		( 0x7F )

/* Dimensions the buffer into which input characters are placed. */
#define cmdMAX_INPUT_SIZE		64
#define configCOMMAND_INT_MAX_OUTPUT_SIZE 512

/* private variables ---------------------------------------------------------*/
static char cli_input[ cmdMAX_INPUT_SIZE + 1];
static char cli_last_input[ cmdMAX_INPUT_SIZE + 1];
static char cli_outbuf[ configCOMMAND_INT_MAX_OUTPUT_SIZE + 1];

/* private function prototypes -----------------------------------------------*/
/* private functions ---------------------------------------------------------*/
void vRegisterSampleCLICommands( void );

/**
	* @vreaf task_usart_cli
	*/
static void task_freertos_cli( void *pvParameters )
{
  int32_t ch, res, inIndex;

  inIndex = 0;
  vRegisterSampleCLICommands();

  cli_getc();
  cli_puts(WELLCOM_MESSAGE);

  for(;;) {
    ch = cli_getc();
    if(ch == '\r' || ch == '\n') {
      if (inIndex > 0) {
        cli_puts(NEW_LINE);
        cli_input[ inIndex  ] = '\0';

        do {
          /* Get the next output string from the command interpreter. */
          res = FreeRTOS_CLIProcessCommand( cli_input, cli_outbuf, configCOMMAND_INT_MAX_OUTPUT_SIZE );
          /* Write the generated string to the UART. */
          cli_puts(cli_outbuf);
        } while( res != pdFALSE );

        inIndex = 0;
        strcpy(cli_last_input, cli_input);
      }
      cli_puts(CMD_TAG);
    }
    /*
     * handle control key
     * up key  : 0x1b 0x5b 0x41
     * down key: 0x1b 0x5b 0x42
     * right key:0x1b 0x5b 0x43
     * left key: 0x1b 0x5b 0x44
     */
    else if (ch == '\x1B') { // up  0x1B 0x5B
      if (cli_getc() == '\x5B') {
        switch ( cli_getc() ) {
        case 'A':
          // clear
          memset(cli_outbuf, '\b', inIndex);
          memset(&cli_outbuf[inIndex], ' ', inIndex);
          memset(&cli_outbuf[inIndex*2], '\b', inIndex);
          cli_outbuf[inIndex*3] = '\0';
          cli_puts(cli_outbuf);
          // copy
          strcpy(cli_input, cli_last_input);
          cli_puts(cli_input);
          inIndex = strlen(cli_input);
          break;

        case 'B':
          memset(cli_outbuf, '\b', inIndex);
          memset(&cli_outbuf[inIndex], ' ', inIndex);
          memset(&cli_outbuf[inIndex*2], '\b', inIndex);
          cli_outbuf[inIndex*3] = '\0';
          cli_puts(cli_outbuf);
          inIndex = 0;
          break;
        }
      }
    } else {
      if( ( ch == '\b' ) || ( ch == cmdASCII_DEL ) ) {
        /* Backspace was pressed.  Erase the last character in the string - if any. */
        if( inIndex > 0 ) {
          inIndex--;
          cli_input[inIndex] = '\0';
          cli_puts("\b \b");
        }
      } else {
        /* A character was entered.  Add it to the string entered so far.  When a \n is
        entered the complete	string will be passed to the command interpreter. */
        if( ( ch >= ' ' ) && ( ch <= '~' ) ) {
          if( inIndex < cmdMAX_INPUT_SIZE ) {
            cli_input[inIndex++] = ch;
            cli_putc(ch);
          }
        }
      }
    }
  }
}
#endif

void task_cli_start(void)
{
#ifdef BSP_CLI_ENABLE
  const char *task_name = "CLI";

  if(xTaskCreate(task_freertos_cli, task_name, 512, NULL, APP_TASK_PRI_CLI, NULL) != pdPASS) {
    DBG_LOGE(TAG, "Create task %s error.", task_name);
  }
#endif
}

/**
  * @}
  */

/******************* (C)COPYRIGHT 2018 ***** END OF FILE *********************/
